package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import com.atguigu.tingshu.account.client.UserAccountFeignClient;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.factory.StrategyFactory;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.strategy.PaymentStrategy;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private UserVipServiceMapper userVipServiceMapper;

    //  重新注入缓存自己的对象。不能使用系统自带的对象。
    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private KafkaService kafkaService;

    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;

    @Autowired
    private TrackInfoFeignClient trackInfoFeignClient;

    @Autowired
    private VipServiceConfigMapper vipServiceConfigMapper;

    @Autowired
    private StrategyFactory strategyFactory;


    @Override
    public void updateVipExpireStatus() {
        //  1.  查询哪些是vip失效的用户并将 is_vip 设置为 0;
        //  update user_info set is_vip = 0 where vip_expire_time < now() and is_vip = 1 and is_deleted = 0;
        userInfoMapper.updateVipExpireStatus();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void userPayRecord(UserPaidRecordVo userPaidRecordVo) {
        //  调用工厂实现类 1001 1002 1003
        PaymentStrategy strategy = strategyFactory.getStrategy(userPaidRecordVo.getItemType());
        //  调用方法
        strategy.processPayment(userPaidRecordVo);
        //  判断用户购买类型：1001
        //        if (userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_ALBUM)) {
        //            //  先查询这个用户记录表中，是否已经存储数据了;
        //            //  select * from user_paid_album where user_id = ? and album_id = ?;
        //            //  根据订单编号查询是否有当前订单 select * from user_paid_album where order_no = ? ;
        //            UserPaidAlbum userPaidAlbumQuery = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getOrderNo, userPaidRecordVo.getOrderNo()));
        //            if (userPaidAlbumQuery != null) return;
        //            //  购买专辑  user_paid_album
        //            UserPaidAlbum userPaidAlbum = new UserPaidAlbum();
        //            //  给属性赋值：
        //            userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
        //            userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
        //            userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
        //            userPaidAlbumMapper.insert(userPaidAlbum);
        //
        //        } else if (userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_TRACK)) {
        //            //  购买声音
        //            Long count = userPaidTrackMapper.selectCount(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getOrderNo, userPaidRecordVo.getOrderNo()));
        //            if (count != 0) return;
        //            //  通过声音Id声音对象;
        //            Long trackId = userPaidRecordVo.getItemIdList().get(0);
        //            //  找声音对象。
        //            Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfoById(trackId);
        //            TrackInfo trackInfo = trackInfoResult.getData();
        //            //  保存数据
        //            userPaidRecordVo.getItemIdList().forEach(itemId -> {
        //                UserPaidTrack userPaidTrack = new UserPaidTrack();
        //                userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
        //                userPaidTrack.setUserId(userPaidRecordVo.getUserId());
        //                userPaidTrack.setAlbumId(trackInfo.getAlbumId());
        //                //  声音Id 对应的应该是一个集合.
        //                userPaidTrack.setTrackId(itemId);
        //                //  保存数据
        //                userPaidTrackMapper.insert(userPaidTrack);
        //            });
        //
        //        } else {
        //            //  购买vip -- user_vip_service
        //            //  根据订单编号查询数据
        //            Long count = userVipServiceMapper.selectCount(new LambdaQueryWrapper<UserVipService>().eq(UserVipService::getOrderNo, userPaidRecordVo.getOrderNo()));
        //            if (count != 0) return;
        //            //  查询用户购买vip时间;
        //            Long vipServiceConfigId = userPaidRecordVo.getItemIdList().get(0);
        //            //  根据Id查询vip服务配置对象
        //            VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(vipServiceConfigId);
        //            Integer serviceMonth = vipServiceConfig.getServiceMonth();
        //            //  创建对象
        //            UserVipService userVipService = new UserVipService();
        //            //  赋值：
        //            userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
        //            userVipService.setUserId(userPaidRecordVo.getUserId());
        //            userVipService.setStartTime(new Date());
        //            //  过期时间：
        //            //  第一次购买当前时间+购买月份！  第二次购买可能会发生--续费： 当前过期时间+续费时间！
        //            //  如何判断是否续费：是否vip and vip_expire > 当前系统时间
        //            UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
        //            //  判断
        //            if (null != userInfo && userInfo.getIsVip() == 1 && userInfo.getVipExpireTime().after(new Date())){
        //                //  userInfo.getVipExpireTime() + userInfo.getServiceMonth();
        //                LocalDateTime localDate = new LocalDateTime(userInfo.getVipExpireTime());
        //                Date expireTime = localDate.plusMonths(serviceMonth).toDate();
        //                userVipService.setExpireTime(expireTime);
        //            } else {
        //                //  不是续费情况.
        //                userVipService.setExpireTime(new LocalDate().plusMonths(serviceMonth).toDate());
        //            }
        //            //  int i = 1/0;
        //            //  保存数据
        //            userVipServiceMapper.insert(userVipService);
        //            //  普通用户变为vip 。user_info.is_vip = 1;
        //            userInfo.setIsVip(1);
        //            userInfo.setVipExpireTime(userVipService.getExpireTime());
        //            userInfoMapper.updateById(userInfo);
        //        }
    }

    /**
     * 根据专辑Id获取用户支付过的声音Id列表
     *
     * @param albumId
     * @param userId
     * @return
     */
    @Override
    public List<Long> findUserPaidTrackList(Long albumId, Long userId) {
        //  select * from user_paid_track track where user_id = 26 and album_id = 341;
        return userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getAlbumId, albumId).eq(UserPaidTrack::getUserId, userId)).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
    }

    @Override
    public Boolean isPaidAlbum(Long albumId, Long userId) {
        //  这个用户是否购买过专辑：
        return userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getAlbumId, albumId).eq(UserPaidAlbum::getUserId, userId)) == null ? false : true;
    }

    /**
     * 判断用户是否购买声音
     *
     * @param albumId     专辑Id
     * @param trackIdList 需要收费的声音Id 列表;
     * @param userId      用户Id
     * @return
     */
    @Override
    public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> trackIdList, Long userId) {
        //  查看用户是否购买过专辑，如果购买过专辑，则需要付费的声音Id集合都需要免费.user_paid_album
        UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getAlbumId, albumId).eq(UserPaidAlbum::getUserId, userId));
        //  判断是否为空
        if (null != userPaidAlbum) {
            //  处理数据 map中的key=trackId value=0或1 1：表示免费 0：表示付费。
            Map<Long, Integer> map = trackIdList.stream().collect(Collectors.toMap(trackId -> trackId, trackId -> 1));
            //  trackIdList.stream().collect(Collectors.toMap(trackId-> trackId, trackId-> 1));
            //  返回数据
            return map;
        }
        //  判断用户是否购买过当前专辑的声音。user_paid_track
        //  select * from user_paid_track paid where user_id = ? and album_id = 1429 and track_id in (trackIdList);
        LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPaidTrack::getUserId, userId).eq(UserPaidTrack::getAlbumId, albumId).in(UserPaidTrack::getTrackId, trackIdList);
        //  获取到当前这个用户购买过的声音Id列表
        List<Long> userPaidTrackIdList = userPaidTrackMapper.selectList(wrapper).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
        //  判断 trackIdList 这个集合中的声音Id 是否有购买过的声音Id.
        Map<Long, Integer> map = new HashMap<>();
        for (Long trackId : trackIdList) {
            //  判断当前集合是否为空
            if (CollectionUtils.isEmpty(userPaidTrackIdList)) {
                //  0 要付费--true;
                map.put(trackId, 0);
            } else {
                //  判断 userPaidTrackIdList 集合中是否包含trackId
                if (userPaidTrackIdList.contains(trackId)) {
                    //  1 免费--false
                    map.put(trackId, 1);
                } else {
                    //  0 要付费--true;
                    map.put(trackId, 0);
                }
            }
        }
        //  返回数据
        return map;
    }

    @Override
    public void updateUser(UserInfoVo userInfoVo, Long userId) {
        //  修改用户信息
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(userInfoVo, userInfo);
        userInfo.setId(userId);
        //  调用修改方法.
        this.updateById(userInfo);
    }

    /**
     * 根据 userId 获取用户信息
     *
     * @param userId
     * @return
     */
    @Override
    public UserInfoVo getUserInfo(Long userId) {
        //  select * from user_info where id = userId;
        UserInfo userInfo = this.getById(userId);
        if (null == userInfo) {
            return null;
        }
        //  属性拷贝
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo, userInfoVo);
        //  返回数据
        return userInfoVo;
    }

    @Override
    //  @Transactional(rollbackFor = Exception.class) 本地事务--只能关联当前的微服务user;不能处理account.
    public Map<String, Object> wxLogin(String code) {
        //	通过code 换取openid; 每个微信用户对应一个唯一的openid.
        String openid = null;
        try {
            //  需要将当前这个微信用户的appId，Secret 传入系统中.
            openid = wxMaService.jsCode2SessionInfo(code).getOpenid();
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        //  通过 openid 查询用户是否注册过.
        //  select wx_open_id from user_info where wx_open_id = 'oZJYB5BJx4zJ07X_7VX0kJ1Xq_hE';
        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));
        //	判断
        if (null == userInfo) {
            //	实现注册功能.
            userInfo = new UserInfo();
            userInfo.setWxOpenId(openid);
            userInfo.setNickname("听友:" + System.currentTimeMillis());
            userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
            //  保存数据
            this.save(userInfo);
            //  初始化账户信息. userAccountFeignClient.initUserAccount(userInfo.getId(),100,100); 同步
            //  失败了? 你想回滚账户注册信息。本地事务解决不了；使用分布式事务！ seata;
            //  userAccountFeignClient.initUserAccount(userInfo.getId(),100,100);
            //  异步：能够提高效率，实现解耦. 发送消息需要传递的参数?
            //  参数一：topics 参数二：消息主体--消息内容是由消费者需求决定！
            kafkaService.sendMsg(KafkaConstant.QUEUE_USER_REGISTER, userInfo.getId().toString());


        }
        //	不为空，注册过. 返回token，并将数据放入缓存中.
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        //	声明一个key来记录
        String loginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
        this.redisTemplate.opsForValue().set(loginKey, userInfo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        //	返回数据
        return map;
    }
}
